home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / ntfs / user / dump.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-15  |  19.0 KB  |  801 lines

  1. /*
  2.  *  dump.c
  3.  *  Output functions for the ntfs tools
  4.  *
  5.  *  Copyright (C) 1995-1997 Martin von L÷wis
  6.  *  Copyright (C) 1997,1999 RΘgis Duchesne
  7.  *  Copyright (c) 1999 Richard Russon
  8.  *
  9.  *  1999/04/05: Merged Security Descriptor dump code from Richard --red
  10.  */
  11.  
  12. #include <errno.h>
  13. #include "ntfstypes.h"
  14. #include "struct.h"
  15. #include "dump.h"
  16. #include "config.h"
  17.  
  18. #include "util.h"
  19. #include "nttools.h"
  20. #include "inode.h"
  21. #include "dir.h"
  22. #include "support.h"
  23. #include <stdio.h>
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifdef HAVE_IO_H
  28. #include <io.h>
  29. #endif
  30. #include <ctype.h>
  31. #include <stdlib.h>
  32. #include "macros.h"
  33.  
  34. /* attribute names. Maybe this gets merged into ntfs_volume some day */
  35. static char* attr_names=0;
  36. static int attr_names_size;
  37.  
  38. /* Dump a block of memory starting at buf. Display length bytes. The displayed
  39.    index of the first byte is start */
  40. void dump_mem(unsigned char *buf, int start, int length)
  41. {
  42.     int offs,i;
  43.     for(offs=0;offs<length;offs+=16)
  44.     {
  45.         printf("%8.8X ",start+offs);
  46.         for(i=0;i<16;i++)printf("%2X ",buf[offs+i]);
  47.         for(i=0;i<16;i++)
  48.             if(buf[offs+i]>31 && buf[offs+i]<128)putchar(buf[offs+i]);
  49.             else putchar('.');
  50.         putchar('\n');
  51.     }
  52. }
  53.  
  54.     
  55.  
  56. /* dump from the raw volume, starting at position */
  57. void dump(ntfs_volume *vol, ntfs_size_t position, int start, int length)
  58. {
  59.     int offset;
  60.     ntfs_lseek(NTFS_FD(vol),position,SEEK_SET);
  61.     for(offset=0;length==-1 || offset<length;offset+=16)
  62.     {
  63.         int i;
  64.         unsigned char buf[16];
  65.         if(read(NTFS_FD(vol),buf,16)!=16)
  66.         {perror("read");return;}
  67.         printf("%8.8X ",start+offset);
  68.         for(i=0;i<16;i++)
  69.             printf("%2X ",buf[i]);
  70.         for(i=0;i<16;i++)
  71.             if(buf[i]>31 && buf[i]<128)putchar(buf[i]);
  72.             else putchar('.');
  73.         putchar('\n');
  74.     }
  75. }
  76.  
  77. static void 
  78. uniprintz(char *first)
  79. {
  80.     while(*first){
  81.         putchar(*first++);
  82.         if(*first++){
  83.             printf("!!!!Error printing string\n");
  84.             return;
  85.         }
  86.     }
  87. }
  88.  
  89.  
  90. /* Find a string on the volume, starting at position. If searching for Unicode
  91.    strings, the string argument should already be Unicode */
  92. #define BSIZE   32768
  93. int grep(ntfs_volume *vol, ntfs_size_t position, int length,
  94.      unsigned char *string, int stringlen, int ignore_case)
  95. {
  96.     int offset;
  97.     int b_offs;
  98.     int i;
  99.     unsigned char buf[2*BSIZE];
  100.  
  101.     if(ignore_case)
  102.         for(i=0;string[i];i++)string[i]=tolower(string[i]);
  103.     ntfs_lseek(NTFS_FD(vol),position,SEEK_SET);
  104.     read(NTFS_FD(vol),buf,BSIZE);
  105.     if(ignore_case)
  106.         for(i=0;i<BSIZE;i++)buf[i]=tolower(buf[i]);
  107.     for(offset=b_offs=0;length==-1 || offset<length;offset+=BSIZE)
  108.     {
  109.         if(read(NTFS_FD(vol),buf+BSIZE,BSIZE)!=BSIZE)
  110.         {perror("read");return -1;}
  111.         if(ignore_case)
  112.             for(i=BSIZE;i<2*BSIZE;i++)buf[i]=tolower(buf[i]);
  113.         for(;b_offs<BSIZE;b_offs++)
  114.             if(buf[b_offs]==string[0])
  115.             {
  116.                 for(i=0;i<stringlen;i++)
  117.                     if(buf[b_offs+i]!=string[i])
  118.                         break;
  119.                 if(i==stringlen)return position+offset+b_offs;
  120.             }
  121.         ntfs_memcpy(buf,buf+BSIZE,BSIZE);
  122.         b_offs-=BSIZE;
  123.     }
  124.     return -1;
  125. }
  126.  
  127. static int
  128. print_attr_type(ntfs_volume* vol,int type)
  129. {
  130.     int offset,error;
  131.     ntfs_u8 *buf=0;
  132.     if(!attr_names){
  133.         ntfs_attribute *data;
  134.         ntfs_io io;
  135.         ntfs_inode attrdef;
  136.         error=ntfs_init_inode(&attrdef,vol,FILE_ATTRDEF);
  137.         if(error)return error;
  138.         offset=0;
  139.         data=ntfs_find_attr(&attrdef,vol->at_data,NULL);
  140.         if(!data){
  141.             free(buf);
  142.             return EINVAL;
  143.         }
  144.         buf=malloc(data->size);
  145.         if(!buf)return ENOMEM;
  146.         io.fn_put=ntfs_put;
  147.         io.fn_get=ntfs_get;
  148.         io.do_read=1;
  149.         io.param=buf;
  150.         io.size=4096;
  151.         error=ntfs_readwrite_attr(&attrdef,data,offset,&io);
  152.         if(error)return error;
  153.         attr_names=buf;
  154.         attr_names_size=data->size;
  155.     }
  156.     for(offset=0;offset<attr_names_size;offset+=0xA0)
  157.         if(NTFS_GETU32(attr_names+offset+0x80)==type){
  158.             uniprintz(attr_names+offset+2);
  159.             break;
  160.         }
  161.     if(offset>=attr_names_size)
  162.         printf("Unknown type");
  163.     return 0;
  164. }
  165.             
  166. /* print the attribute list for the MFT record at offset on the volume */
  167. void list_attributes(ntfs_volume *vol, ntfs_size_t offset)
  168. {
  169.     char rec[4096];
  170.     ntfs_lseek(NTFS_FD(vol),offset,SEEK_SET);
  171.     if(read(NTFS_FD(vol),rec,sizeof(rec))!=sizeof(rec)){
  172.         perror("read");
  173.         return;
  174.     }
  175.     if(!ntfs_check_mft_record(vol,rec)){
  176.         fprintf(stderr,"Not a mft record\n");
  177.         return;
  178.     }
  179.     list_attr_mem(vol,rec);
  180. }
  181.  
  182. /* dump the standard information attribute */
  183. static void dump_standard_information(ntfs_u8 *start)
  184. {
  185.     printf("\tCreation time ");
  186.     print_time(NTFS_GETU64(start));
  187.     printf("\n\tModification time ");
  188.     print_time(NTFS_GETU64(start + 0x8));
  189.     printf("\n\tMFT Modification time ");
  190.     print_time(NTFS_GETU64(start + 0x10));
  191.     printf("\n\tAccess time ");
  192.     print_time(NTFS_GETU64(start + 0x18));
  193.     printf("\n");
  194. }
  195.  
  196. /* dump the attribute list attribute */
  197. static void dump_attribute_list(ntfs_u8 *start, ntfs_u8 *stop)
  198. {
  199.     while(start!=stop){
  200.         printf("\tType %X,MFT# %X,Start VCN %X ",NTFS_GETU32(start),
  201.                NTFS_GETU32(start+0x10),NTFS_GETU32(start+0x8));
  202.         uniprint(start+0x1A,NTFS_GETU8(start+0x6));
  203.         start+=NTFS_GETU16(start+4);
  204.         putchar('\n');
  205.     }
  206. }
  207.  
  208. static void print_name(ntfs_u8 *first)
  209. {
  210.     int length=*(unsigned char*)first++;
  211.     switch(*first++)
  212.     {
  213.     case 0: printf("Posix-Name:");break;
  214.     case 1: printf("Unicode-Name:");break;
  215.     case 2: printf("DOS-Name:");break;
  216.     case 3: printf("Unicode+DOS:");break;
  217.     default:
  218.         printf("Don't know how to read the name\n");
  219.         return;
  220.     }
  221.     uniprint(first,length);
  222.     puts("");
  223. }
  224.  
  225. /* dump the filename attribute */
  226. static void dump_filename(ntfs_u8 *start)
  227. {
  228.     printf("\t");
  229.     print_name(start+0x40);
  230.     printf("\tIndexed in 0x%X\n",NTFS_GETU32(start));
  231. }
  232.  
  233. /* dump a sid */
  234. long dump_sid (ntfs_u8 *sid)
  235. {
  236.     int revision;
  237.     int sa_count;
  238.     int i;
  239.     ntfs_u64 ident_auth = 0;
  240.  
  241.     revision = *sid;                        /* Should always be 1 */
  242.     sid++;
  243.     sa_count = *sid;                        /* Number of Sub-authorities */
  244.     sid++;
  245.  
  246.     for (i = 0; i < 6; i ++)
  247.     {
  248.         ident_auth <<= 8;
  249.         ident_auth += *sid;
  250.         sid++;
  251.     }
  252.  
  253.     printf ("S-%d-%Lu", revision, ident_auth);
  254.  
  255.     for (i = 0; i < sa_count; i++)
  256.     {
  257.         printf ("-%u", *((ntfs_u32*) sid));
  258.         sid += 4;
  259.     }
  260.  
  261.     return 8 + (sa_count * 4);
  262. }
  263.  
  264. void display_access_flags (ntfs_u8 flags)
  265. {
  266.     if (flags & 0x1) printf (" Obj inh ACE");
  267.     if (flags & 0x2) printf (" Con inh ACE");
  268.     if (flags & 0x4) printf (" No prop inh");
  269.     if (flags & 0x8) printf (" Inh onlyACE");
  270. }
  271.  
  272. void display_access_mask (ntfs_u32 mask)
  273. {
  274.     if ((mask & 0x00120089) == 0x00120089) printf ("R"); else printf (".");
  275.     if ((mask & 0x00120116) == 0x00120116) printf ("W"); else printf (".");
  276.     if ((mask & 0x001200a0) == 0x001200a0) printf ("X"); else printf (".");
  277.     if ((mask & 0x00010000) == 0x00010000) printf ("D"); else printf (".");
  278.     if ((mask & 0x00040000) == 0x00040000) printf ("P"); else printf (".");
  279.     if ((mask & 0x00080000) == 0x00080000) printf ("O"); else printf (".");
  280. }
  281.  
  282. void display_access_allowed_ace (ntfs_u8 *ace)
  283. {
  284.     ntfs_u32 mask  = NTFS_GETU32 (ace + 4);
  285.     ntfs_u8  flags = NTFS_GETU8  (ace + 1);
  286.  
  287.     display_access_mask (mask);
  288.     display_access_flags (flags);
  289. }
  290.  
  291. void display_access_denied_ace (ntfs_u8 *ace)
  292. {
  293.     ntfs_u32 mask  = NTFS_GETU32 (ace + 4);
  294.     ntfs_u8  flags = NTFS_GETU8  (ace + 1);
  295.  
  296.     display_access_mask (mask);
  297.     display_access_flags (flags);
  298. }
  299.  
  300. void display_system_audit_ace (ntfs_u8 *ace)
  301. {
  302.     ntfs_u32 mask  = NTFS_GETU32 (ace + 4);
  303.     ntfs_u8  flags = NTFS_GETU8  (ace + 1);
  304.  
  305.     display_access_mask (mask);
  306.  
  307.     if (flags & 0x80) printf (" Success ");
  308.     if (flags & 0x40) printf (" Failure ");
  309. }
  310.  
  311. long display_ace (ntfs_u8 *ace)
  312. {
  313.     ntfs_u8  type     = NTFS_GETU8  (ace);
  314.     //ntfs_u8  flags    = NTFS_GETU8  (ace + 1);
  315.     ntfs_u16 ace_size = NTFS_GETU16 (ace + 2);
  316.     ntfs_u32 mask     = NTFS_GETU32 (ace + 4);
  317.     long sid_size     = 0;
  318.  
  319.     switch (type)
  320.     {
  321.         case 0x00:
  322.             printf ("\t\tAccess allowed: ");
  323.             display_access_allowed_ace(ace);
  324.             break;
  325.  
  326.         case 0x01:
  327.             printf ("\t\tAccess denied:  ");
  328.             display_access_denied_ace(ace);
  329.             break;
  330.  
  331.         case 0x02:
  332.             printf ("\t\tSystem audit:   ");
  333.             display_system_audit_ace(ace);
  334.             break;
  335.  
  336.         default:
  337.             printf ("\t\tUnknown:        %#010x\n", mask);
  338.             return ace_size;
  339.     }
  340.  
  341.     printf (" ");
  342.     sid_size = dump_sid (ace + 8);
  343.     printf ("\n");
  344.  
  345.     if (sid_size != ace_size) {
  346.         // I've seen this happen
  347.     }
  348.  
  349.     return ace_size;
  350. }
  351.  
  352. long display_acl (ntfs_u8 *acl, int len)
  353. {
  354.     //ntfs_u8  version  = NTFS_GETU8  (acl);
  355.     //ntfs_u8  unknown1 = NTFS_GETU8  (acl + 1);
  356.     ntfs_u32 acl_size = NTFS_GETU16 (acl + 2);
  357.     ntfs_u32 num_aces = NTFS_GETU16 (acl + 4);
  358.     //ntfs_u32 unknown2 = NTFS_GETU16 (acl + 6);
  359.  
  360.     long l;
  361.     long size = 8;
  362.  
  363.     printf (" %d entr%s\n", num_aces, num_aces == 1 ? "y" : "ies");
  364.  
  365.     if (acl_size < len)
  366.     {
  367.         for (l = 0; l < num_aces; l++)
  368.         {
  369.             size += display_ace (acl + size);
  370.         }
  371.     }
  372.  
  373.     return size;
  374. }
  375.  
  376. /* dump the security descriptor attribute */
  377. static void dump_security_descriptor(ntfs_u8 *start, int len)
  378. {
  379.     //ntfs_u32 unknown       = NTFS_GETU32 (start);         // This looks like flags
  380.     ntfs_u32 off_user      = NTFS_GETU32 (start + 0x4);     // user SID
  381.     ntfs_u32 off_group     = NTFS_GETU32 (start + 0x8);     // group SID
  382.     ntfs_u32 off_acl_audit = NTFS_GETU32 (start + 0xC);     // ACL containing audit info
  383.     ntfs_u32 off_acl_perms = NTFS_GETU32 (start + 0x10);    // ACL containing permission info
  384.  
  385.     /* When the Audit ACL is missing, its offset is zeroed */
  386.     if (off_acl_audit && off_acl_audit < len) {
  387.         printf ("\tACL - Audit");
  388.         display_acl (start + off_acl_audit, len);
  389.     }
  390.     if (off_acl_perms < len) {
  391.         printf ("\tACL - Permissions");
  392.         display_acl (start + off_acl_perms, len);
  393.     }
  394.     if (off_user < len) {
  395.         printf ("\tUser:  ");
  396.         dump_sid (start + off_user);
  397.         printf ("\n");
  398.     }
  399.     if (off_group < len) {
  400.         printf ("\tGroup: ");
  401.         dump_sid (start + off_group);
  402.         printf ("\n");
  403.     }
  404. }
  405.  
  406. /* display the list of runs of an attribute */
  407. static void dump_runs(unsigned char *start, int vcnstart, int vcnend,
  408.     int compressed)
  409. {
  410.     int length=0;
  411.     ntfs_cluster_t cluster=0;
  412.     int l=vcnend-vcnstart;
  413.     int vcn=vcnstart;
  414.     int ctype;
  415.     while(l>0 && ntfs_decompress_run(&start,&length,&cluster,&ctype)!=-1)
  416.     {
  417.         l-=length;
  418.         if(!ctype)
  419.             printf("\tRun from %x to %x (VCN=%x)\n",cluster,cluster+length-1,vcn);
  420.         else
  421.             printf("\tCompression unit size %x\n",length);
  422.         vcn+=length;
  423.     }
  424. }
  425.  
  426. /* print the attribute list at rec */
  427. void list_attr_mem(ntfs_volume *vol, char *rec)
  428. {
  429.     int offs;
  430.     int type, attr_length, stream_length, resident, namelen, compressed;
  431.     char *start;
  432.     /* first attribute should start at *0x14 */
  433.     offs= NTFS_GETU16(rec + 0x14);
  434.     while(offs<vol->mft_recordsize)
  435.     {
  436.         printf("%4.4X:",offs);
  437.         printf("Type %X ",type=NTFS_GETU32(rec+offs));
  438.         if(type==-1)break;
  439.         /* offset to the next attribute */
  440.         printf("Length %X ", attr_length = NTFS_GETU32(rec + offs + 0x4));
  441.         resident=*(rec+offs+8)=='\0';
  442.         compressed=*(rec+offs+0xC);
  443.         if(resident){
  444.             stream_length = NTFS_GETU32(rec + offs + 0x10);
  445.             printf("resident ");
  446.             if(*(rec+offs+0x16))
  447.                 printf("indexed ");
  448.         }
  449.         if(compressed)
  450.             printf("compressed ");
  451.         printf("Slot #%X ",NTFS_GETU16(rec+offs+14));
  452.         /* position of attribute data if resident */
  453.         start=rec+offs+NTFS_GETU8(rec+offs+10);
  454.         if(NTFS_GETU8(rec+offs+10)==0)start+=NTFS_GETU16(rec+offs+0x20);
  455.         /* length attribute name, name starts at start */
  456.         namelen=NTFS_GETU8(rec+offs+9);
  457.         if(namelen!=0)
  458.         {
  459.             printf("named(");
  460.             uniprint(start,namelen);
  461.             start+=namelen*2;
  462.             printf(") ");
  463.         }
  464.         if(NTFS_GETU8(rec+offs+11))
  465.             fprintf(stderr,"Found [B] at offset %X\n",offs);
  466.         if(NTFS_GETU8(rec+offs+13))
  467.             fprintf(stderr,"Found [D] at offset %X\n",offs);
  468.         print_attr_type(vol,type);
  469.         printf("\n");
  470.         if(resident)
  471.             printf("\tStream length 0x%X \n", stream_length);
  472.         switch(type)
  473.         {
  474.         case 0x10:
  475.             dump_standard_information(rec + offs + 0x18);
  476.             break;
  477.         case 0x20:
  478.             dump_attribute_list(rec + offs + 0x18, rec + offs + 0x18 + stream_length);
  479.             break;
  480.         case 0x30:
  481.             dump_filename(rec + offs + 0x18);
  482.             break;
  483.         case 0x50:
  484.             if (resident)
  485.                 dump_security_descriptor(rec + offs + 0x18, stream_length);
  486.             break;
  487.         }
  488.         if(!resident) {
  489.             printf("\tAllocated %x, size %x, initialized %x",
  490.                    NTFS_GETU32(rec+offs+0x28),NTFS_GETU32(rec+offs+0x30),
  491.                    NTFS_GETU32(rec+offs+0x38));
  492.             if(compressed)
  493.                 printf(", compressed %x\n",NTFS_GETU32(rec+offs+0x40));
  494.             else
  495.                 putchar('\n');
  496.             if(NTFS_GETU16(rec+offs+0x22))
  497.                 fprintf(stderr,"Found [22]=%x at offset %X\n",NTFS_GETU16(rec+offs+0x22),offs);
  498.             if(NTFS_GETU32(rec+offs+0x24))
  499.                 fprintf(stderr,"Found [24] at offset %X\n",offs);
  500.             dump_runs(start,NTFS_GETU32(rec+offs+0x10),
  501.                   NTFS_GETU32(rec+offs+0x18),compressed);
  502.         }
  503.         offs += attr_length;
  504.     }
  505.     puts("");
  506. }       
  507.  
  508. /* Necessary forward reference */
  509. static void dumpdir_entry(ntfs_inode* ino,char *entry);
  510.  
  511. /* display a directory record */
  512. static void dumpdir_record(ntfs_inode* ino,int nextblock)
  513. {
  514.     int length,error;
  515.     char record[8192];
  516.     char *offset;
  517.     ntfs_io io;
  518.  
  519.     io.fn_put=ntfs_put;
  520.     io.fn_get=0;
  521.     io.param=record;
  522.     io.size=ino->u.index.recordsize;
  523.     error=ntfs_read_attr(ino,ino->vol->at_index_allocation,"$I30",
  524.                  nextblock*ino->vol->clustersize,&io);
  525.     if(error || io.size!=ino->u.index.recordsize){
  526.         printf("read failed\n");
  527.         return;
  528.     }
  529.     if(!ntfs_check_index_record(ino,record)){
  530.         printf("Not a index record\n");
  531.         return;
  532.     }
  533.     offset=record+NTFS_GETU16(record+0x18)+0x18;
  534.     do{
  535.         dumpdir_entry(ino,offset);
  536.         if(*(offset+0xC)&2)break;
  537.         length=NTFS_GETU16(offset+8);
  538.         if(!length)break;
  539.         offset+=length;
  540.     }while(1);
  541. }
  542.  
  543. /* display all subentries, then display this entry */
  544. static void dumpdir_entry(ntfs_inode* ino,char *entry)
  545. {
  546.     int length=NTFS_GETU16(entry+8);
  547.     int used=(NTFS_GETU8(entry+12)&2)==0;
  548.     if(used)printf("\tinode %x\t",NTFS_GETU32(entry));
  549.     if(NTFS_GETU8(entry+13))
  550.         fprintf(stderr,"Found [D] at %x\n",ino->i_number);
  551.     if(NTFS_GETU16(entry+14))
  552.         fprintf(stderr,"Found [E] at %x\n", ino->i_number);
  553.     if((int)NTFS_GETU8(entry+12)&1){
  554.         int nextblock=NTFS_GETU64(entry+length-8);
  555.         printf("Going down to block %x\n",nextblock);
  556.         dumpdir_record(ino,nextblock);
  557.         printf("back to\tinode %x\t",NTFS_GETU32(entry));
  558.     }
  559.     if(used)print_name(entry+0x50);
  560. }
  561.  
  562. /* display an inode as directory */
  563. void dumpdir(ntfs_inode *ino)
  564. {
  565.     int length=ino->vol->mft_recordsize;
  566.     char *buf=(char*)malloc(length);
  567.     char *data;
  568.     ntfs_io io;
  569.  
  570.     io.fn_put=ntfs_put;
  571.     io.fn_get=0;
  572.     io.param=buf;
  573.     io.size=length;
  574.     if(ntfs_read_attr(ino,ino->vol->at_index_root,"$I30",0,&io))
  575.     {
  576.         printf("Not a directory\n");
  577.         free(buf);
  578.         return;
  579.     }
  580.     ino->u.index.recordsize=NTFS_GETU32(buf+0x8);
  581.     ino->u.index.clusters_per_record=NTFS_GETU32(buf+0xC);
  582.     /* FIXME: consistency check */
  583.     data=buf+0x20;
  584.     while(1)
  585.     {
  586.         length=NTFS_GETU16(data+8);
  587.         dumpdir_entry(ino,data);
  588.         if(NTFS_GETU8(data+12)&2)break;
  589.         data+=length;
  590.         if(!length){
  591.             printf("length==0!!\n");
  592.             break;
  593.         }
  594.     }
  595.     free(buf);
  596. }
  597.  
  598. #if 0
  599. static void putchar1(unsigned char c)
  600. {
  601.     if(c>=32 && c<=127)
  602.         putchar(c);
  603.     else switch(c)
  604.     {
  605.     case 10: printf("\\n");break;
  606.     case 13: printf("\\r");break;
  607.     default: printf("\\%o",c);
  608.     }
  609. }
  610. #endif
  611.  
  612. void dump_decompress(ntfs_inode *ino, int run, int verbose)
  613. {
  614.     printf("Function is obsolete\n");
  615.     /* FIXME: really? */
  616. #if 0
  617.     int block,len,clear_pos;
  618.     unsigned char *compressed;
  619.     char clear[16384];
  620.     int tag=0,bits,charmode;
  621.     int ctype;
  622.     unsigned char *data;
  623.     int offset=0;
  624.     unsigned char *attr=ntfs_get_attr(ino,AT_DATA,0);
  625.     ntfs_io io;
  626.  
  627.     io.fn_put=ntfs_put;
  628.     io.fn_get=0;
  629.     if(!attr)
  630.     {
  631.         fprintf(stderr,"No data attribute in this inode\n");
  632.         return;
  633.     }
  634.     if(attr->resident)
  635.     {
  636.         fprintf(stderr,"Attribute is resident\n");
  637.         return;
  638.     }
  639.     if(!attr->compressed)
  640.     {
  641.         fprintf(stderr,"Data attribute is not compressed\n");
  642.         return;
  643.     }
  644.     /*Skip name and valueoffset*/
  645.     attr+=NTFS_GETU16(attr+0x20)+NTFS_GETU8(attr+9);
  646.     block=0;
  647.     do{
  648.         ntfs_decompress_run(&attr,&len,&block,&ctype);
  649.     }while(run--);
  650.     compressed=(char*)malloc(len*vol->clustersize);
  651.     io.param=compressed;
  652.     io.do_read=1;
  653.     error=ntfs_getput_clusters(vol,block,0,
  654.                    len*vol->clustersize,&io);
  655.     if(error)
  656.         fprintf(stderr,"Error reading block %x\n",block);
  657.     data=compressed;
  658.     while(*(data+1) & 0xF0)
  659.     {
  660.         int block_size;
  661.         unsigned char *stop;
  662.         block_size = *(unsigned short*)data;
  663.         if(verbose)printf("Head %x",block_size);
  664.         block_size &= 0xFFF;
  665.         data+=2;
  666.         offset+=2;
  667.         stop = data + block_size;
  668.         bits=0;
  669.         charmode=0;
  670.         clear_pos=0;
  671.         while(data<=stop)
  672.         {
  673.             if(!bits){
  674.                 if(verbose)printf("\nOffset %x",offset);
  675.                 charmode=0;
  676.                 tag=*data;
  677.                 bits=8;
  678.                 data++;
  679.                 offset++;
  680.                 if(data>stop)
  681.                     break;
  682.             }
  683.             if(tag&1){
  684.                 int i,len,delta,delta1=0;
  685.                 delta = *(unsigned short*)(data);
  686.                 len=*data;
  687.                 len&=0x1f;
  688.                 if(clear_pos<=0x10)
  689.                 {
  690.                     delta1=delta>>12;
  691.                     len = delta & 0xFFF;
  692.                 }
  693.                 else if(clear_pos<=0x20)
  694.                 {
  695.                     delta1=delta>>11;
  696.                     len = delta & 0x7FF;
  697.                 }
  698.                 else if(clear_pos<=0x40)
  699.                 {
  700.                     delta1=delta>>10;
  701.                     len = delta & 0x3FF;
  702.                 }
  703.                 else if(clear_pos<=0x80)
  704.                 {
  705.                     delta1=delta>>9;
  706.                     len = delta & 0x1FF;
  707.                 }
  708.                 else if(clear_pos<=0x100)
  709.                 {
  710.                     delta1=delta>>8;
  711.                     len = delta & 0xFF;
  712.                 }
  713.                 else if(clear_pos<=0x200)
  714.                 {
  715.                     delta1=delta>>7;
  716.                     len = delta & 0x7F;
  717.                 }
  718.                 else if(clear_pos<=0x400)
  719.                 {
  720.                     delta1=delta>>6;
  721.                     len = delta & 0x3F;
  722.                 }
  723.                 else if(clear_pos<=0x800)
  724.                 {
  725.                     delta1=delta>>5;
  726.                     len = delta & 0x1F;
  727.                 }
  728.                 else if(clear_pos<=0x1000)
  729.                 {
  730.                     delta1=delta>>4;
  731.                     len = delta & 0xF;
  732.                 }else
  733.                     fprintf(stderr,"NOW WHAT?\n");
  734.                 len+=3;
  735.                 if(verbose)printf("\n%8.8X:len %x(%x) delta %x(%x) ",
  736.                           clear_pos,len,*data,delta,delta1);
  737.                 charmode=0;
  738.                 for(i=0;i<len;i++)
  739.                 {
  740.                     if(verbose)
  741.                         putchar1(clear[clear_pos-delta1-1]);
  742.                     else
  743.                         putchar(clear[clear_pos-delta1-1]);
  744.                     clear[clear_pos]=clear[clear_pos-delta1-1];
  745.                     clear_pos++;
  746.                 }
  747.                 data+=2;
  748.                 offset+=2;
  749.             }else{
  750.                 if(verbose)if(!charmode)
  751.                     printf("\n%8.8X:",clear_pos);
  752.                 if(verbose)
  753.                     putchar1(*data);
  754.                 else
  755.                     putchar(*data);
  756.                 clear[clear_pos++]=*data;
  757.                 data++;
  758.                 offset++;
  759.                 charmode=1;
  760.             }
  761.             tag>>=1;
  762.             bits--;
  763.         }
  764.         if(verbose)putchar('\n');
  765.     }/*while*/
  766. #endif
  767. }
  768.  
  769. void dump_inode(ntfs_inode *ino)
  770. {
  771.     int i,j,vcn;
  772.     printf("Inode %d, %d attributes, %d mft clusters\n",
  773.            ino->i_number, ino->attr_count, ino->record_count);
  774.     for(i=0;i<ino->attr_count;i++)
  775.     {
  776.         printf("attribute %X",ino->attrs[i].type);
  777.         if(ino->attrs[i].name)
  778.         {
  779.             printf(" named(");
  780.             uniprint((char*)ino->attrs[i].name,ino->attrs[i].namelen);
  781.             printf(")\n");
  782.         }else
  783.             printf("\n");
  784.         if(ino->attrs[i].resident)
  785.             printf("  resident\n");
  786.         else
  787.             for(j=0,vcn=0;j<ino->attrs[i].d.r.len;j++)
  788.             {
  789.                 printf("  Run %d from %x len %x (VCN=%x)\n", j,
  790.                        ino->attrs[i].d.r.runlist[j].cluster,
  791.                        ino->attrs[i].d.r.runlist[j].len,vcn);
  792.                 vcn+=ino->attrs[i].d.r.runlist[j].len;
  793.             }
  794.     }
  795. }
  796. /*
  797.  * Local variables:
  798.  * c-file-style: "linux"
  799.  * End:
  800.  */
  801.